//! Upravljanje prekidima - razina jezgre

/* Obrada prekida ide na slijedeci nacin:
   * u "arh" sloju su za svaki prekid definirane funkcije, ali te funkcije su
     iste i pozivaju "j_prekidna_funkcija" koje dalje delegira posao

   * skraceno:

     prekid_x: //u arh sloju
	...
	j_prekidna_funkcija(x, kontekst);
	...
	iret
*/

#define _J_PREKIDI_C_
#include "prekidi.h"

#include "dretve.h"
#include "procesi.h"
#include "razno.h"
#include "ispis.h"
#include "pozivi_jezgre.h"
#include "postavke.h"
#include <arh/prekidi.h>

//opisnici prekida
prekid_t j_prekidna_f[PREKIDI_BROJ];
//uz ovu implementaciju za neki sklopovski prekid moze biti samo 1. funkcija!
//ako treba vise, onda treba ovo nadograditi

//poziva se iz arh dijela kao funkcija koja obradjuje prekide
void j_prekidna_funkcija ( int id, void *vrh_stoga )
{
	arh_pohrani_okolinu_dretve ( j_dohvati_kontekst_aktivne(), vrh_stoga );

	if ( j_prekidna_f[id] != NULL )
		j_prekidna_f[id] ( id, vrh_stoga );
	else
		j_prekid_nedefiniran ( id );

	arh_pripravi_okolinu_dretvi ( j_dohvati_kontekst_aktivne() );
}

//definira prihvat prekida za pojedini prekid
prekid_t j_prekidi_postavi (int id, prekid_t obrada)
{
	prekid_t stara_funkcija = NULL;

	if (id <0 || id > PREKIDI_BROJ) {
		j_ispisi("ID prekida izvan granica\n");
	}
	else {
		stara_funkcija = j_prekidna_f[id];
		j_prekidna_f[id] = obrada;
	}

	return stara_funkcija;
}

//definirano u dretve.c 
extern void *j_prekidni_stog; //vrh stoga za jezgrine funkcije (u prekidu)

//inicijalizira prekidni podsustav (brise sve)
void j_prekidi_inicijaliziraj ()
{
	arh_prekidi_inicijaliziraj(j_prekidna_funkcija, j_prekidni_stog);
	
	memset(j_prekidna_f, 0, sizeof(j_prekidna_f));

	j_prekidi_postavi(PREKIDI_PROGRAMSKI, (prekid_t) j_pozivi_jezgre);
}


void j_prekid_nedefiniran (int n)
{
	j_ispisi("Prekid za koje nije definirano ponasanje (%d) ", n);
	j_ispisi("%s\n", arh_opis_prekida(n));
	j_ispisi("Aktivna dretva = %d\n", j_id_dretve(NULL));
	
	j_zaustavi_potpuno("Obustavljam daljnji rad!");
}